package com.yzf.demo.demo.Thread;

/**
 * Created by 于占峰 on 2020/4/1/001.
 * .Happens-Before规则
 * <p>
 * Happens-Before是一种可见性规则,它表达的含义是前面一个操作的结果对后续操作是可见的;
 */
public class HappensBeforeDemo {

    /**
     * 程序顺序规则;
     * <p>
     * as-id-serial规则,在单线程中,不管怎么重排序,单线程的执行结果都是一定的,为了遵守规则,编译器和处理器不会对存在数据依赖关系的程序重排序.
     * <p>
     * 传递性规则:
     * <p>
     * 如果A Happens-Before B ,且B Happens-Before C,那么A Happens-Before C;
     */
    class volatitleExample {
        int x = 0;
        volatile boolean v = false;

        public void writer() {
            x = 42;
            v = true;
        }

        public void reader() {
            if (v == true) {
                //x = 42
            }
        }
    }

    /**
     * 监视器锁规则:
     * <p>
     * 对一个锁的解锁 Happens-Before 于后续对这个锁加锁;
     */
    class syncclassDemo {
        int x = 0;
        volatile boolean v = false;

        public void demo() {
            synchronized (this) {//此处自动加锁
                if (this.x < 12) {
                    this.x = 12;
                }
            }//此处自动解锁
        }
    }
    /**
     * ##### volatile变量规则:
     *
     * ###### 	对于一个volatitle域的写, Happens-Before 于任意后续对这个volatile的域读;
     */


    /**
     * ##### start()规则:
     * <p>
     * 如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作Happens-Before于线程B中的任意操作;
     */
    public static void main(String[] args) {
        int i = 66;
        Thread B = new Thread(() -> {
            /**
             * 主线程调用B.start()之前
             * 所有对共享变量的修改,处处皆可见
             */
        });
        i = 76;
        //main主线程启动子线程B
        B.start();
    }

    /**
     * join()规则:
     * <p>
     * 如果线程A执行ThreadB.join()并成功返回,那么线程B中的任意操作Happens-Before于线程A从ThredB.hoin()操作成功返回;
     */
    int var = 1;

    public void demoMethod() throws InterruptedException {
        Thread B = new Thread(() -> {
            //此处共享变量var修改
            var = 2;
        });
        //例如此处对共享变量修改
        var = 66;
        //则这个修改结果对线程B可见
        //主线程启动子线程
        B.start();
        B.join();
        //子线程所有对共享变量的修改
        //在主线程调用B.join()之后皆可见
    }
}
